using System;
using System.Collections.Generic;
using System.Text;
using TVDesigner.Generator.Components;
using System.IO;
using System.Diagnostics;
using System.Threading;

namespace TVDesigner.Generator
{
    public class Generator
    {
		private static Generator instance = null;
		private GenerateInstructions _Instructions;

		public GenerateInstructions Instructions {
			get { return _Instructions; }
			set { _Instructions = value; }
		}

        private ProjectXlet _ProjectXlet;

        public ProjectXlet ProjectXlet
        {
            get { return _ProjectXlet; }
            set { _ProjectXlet = value; }
        }
        

		private Generator () {

		}

		public static Generator Instance
		{
			get
			{
				if (instance == null)
					instance = new Generator();
				return instance;
			}
		}

        public void CreateProject(GenerateInstructions instructions)
        {
			_Instructions = instructions;

            System.IO.DirectoryInfo projectFolder = null;
            System.IO.DirectoryInfo dirInfoSRC = null;
            System.IO.DirectoryInfo dirInfoBIN = null;
            System.IO.DirectoryInfo dirInfoLIB = null;
            System.IO.DirectoryInfo dirDataFolder = null;

            System.IO.DirectoryInfo srcFolder = null;
            System.IO.DirectoryInfo libFolder = null;
            System.IO.DirectoryInfo dataFolder = null;


            //criar as pastas.
            if (!System.IO.Directory.Exists(instructions.Location + "\\" + instructions.ProjectName))
            {
                projectFolder = System.IO.Directory.CreateDirectory(instructions.Location + "\\" + instructions.ProjectName);

                if (!instructions.SameFolder)
                {
                    dirInfoSRC = projectFolder.CreateSubdirectory("src");
                    dirInfoBIN = projectFolder.CreateSubdirectory("bin");
                    dirInfoLIB = projectFolder.CreateSubdirectory("lib");
                    dirDataFolder = projectFolder.CreateSubdirectory("data");
                }
            }


            string package = string.Empty;

            //setando a pasta onde criar os arquivos "src"
            if (instructions.SameFolder)
            {
                srcFolder = projectFolder;
                libFolder = projectFolder;
                dataFolder = projectFolder.CreateSubdirectory("data");
            }
            else
            {
                package = instructions.ProjectName.ToLower();

                srcFolder = dirInfoSRC.CreateSubdirectory(instructions.ProjectName.ToLower());
                libFolder = dirInfoLIB;
                dataFolder = dirDataFolder;
            }


            //criar o xlet.
            _ProjectXlet = new ProjectXlet(instructions.ProjectName, instructions.ParseElements);

            string projectXletContent = _ProjectXlet.DeclareClass(package);

            FileGeneratorParameters fgp = new FileGeneratorParameters(_ProjectXlet.NameStartedWithUpperCase,
                    srcFolder.FullName, "java", projectXletContent);

            FileGenerator.CreateFile(fgp);


            //criar "TVDesignerScreen" (abstract).
            string hAbstractScreenFileContent = TVDesignerScreen.DeclareClass(package,
                _ProjectXlet.NameStartedWithUpperCase);

            fgp = new FileGeneratorParameters("TVDesignerScreen",
                    srcFolder.FullName, "java", hAbstractScreenFileContent);

            FileGenerator.CreateFile(fgp);


            //criar "TVDesignerKeyListener" .
            string hATVDesignerKeyListenerFileContent = TVDesignerKeyListener.DeclareClass(package,
                _ProjectXlet.NameStartedWithUpperCase);

            fgp = new FileGeneratorParameters("TVDesignerKeyListener",
                    srcFolder.FullName, "java", hATVDesignerKeyListenerFileContent);

            FileGenerator.CreateFile(fgp); 


            //criar as telas.
            foreach (Screen screen in instructions.ParseElements.Screens)
            {
                string hScreenFileContent = screen.DeclareClass(package,
                    _ProjectXlet.NameStartedWithUpperCase);

                fgp = new FileGeneratorParameters(screen.NameStartedWithUpperCase,
                        srcFolder.FullName, "java", hScreenFileContent);

                FileGenerator.CreateFile(fgp);
            }


            //copiando o jar para a pasta destino.
            File.WriteAllBytes((libFolder.FullName + "\\" + "mhpstubs.jar"),
                TVDesigner.Properties.Resources.mhpstubs);

            //copiando o ImagesController do resource e colocando no lugar dele.
            this.CreateImagesController(package, srcFolder.FullName);
            

            //copiar imagens para a pasta data.
            foreach (ImageFile imageFile in instructions.ParseElements.ImageFiles)
            {
                string destinationFile = string.Concat(dataFolder.FullName,
                    "\\", imageFile.FileNameWithExtension);

                if (!File.Exists(destinationFile))
                {
                    File.Copy(imageFile.FullName, destinationFile);
                }
            }


            //gerar o compilador e compilar.
            this.Compile(instructions.SameFolder, projectFolder.FullName,
                _ProjectXlet.NameStartedWithUpperCase, package, instructions.HasSystemVariables,
                instructions.JavacLocation, dataFolder.FullName);
        }

        private void CreateImagesController(string package, string sourceFolder)
        {
            string imagesController = TVDesigner.Properties.Resources.ImagesController;

            string imagesControllerContent = imagesController;

            if (!package.Equals(string.Empty))
            {
                imagesControllerContent = string.Concat("package ", package, ";", imagesController);
            }

            FileGeneratorParameters fgp = new FileGeneratorParameters("ImagesController",
                sourceFolder, "java", imagesControllerContent);

            FileGenerator.CreateFile(fgp);
        }

        private void Compile(bool isSameFolder, string projectFolder, string mainClassName,
            string package, bool hasSystemVariables, string javacLocation, string dataFolder)
        {
            string copyString = string.Empty;

            if (isSameFolder)
            {
                package = string.Empty;
            }
            else
            {
                copyString = string.Concat(@"xcopy /e/y data bin\data\");
            }
            
            string enterPathString = string.Concat("cd ", projectFolder, "\n");

            //string javaCompiler = "\"C:\\Sun\\SDK\\jdk\\bin\\javac\"";
            string javaCompiler = null;

            if (hasSystemVariables)
            {
                javaCompiler = "javac";
            }
            else
            {
                javaCompiler = string.Concat("\"", javacLocation, "\"");
            }

            string compileString = string.Concat(
                javaCompiler,
                (isSameFolder) ? string.Empty : " -d ./bin",
                " -classpath ./;",
                (isSameFolder) ? "./mhpstubs.jar " : "./lib/mhpstubs.jar -sourcepath ./src/ src/",
                package,
                (isSameFolder) ? string.Empty : "/",
                mainClassName,
                ".java\n"
                );

            string compileFileContent = string.Concat
                (
                    enterPathString, "\n",
                    compileString, "\n",
                    copyString, "\n",
                    "PAUSE\n"
                );

            FileGeneratorParameters fgp = new FileGeneratorParameters("Compiler", projectFolder, "bat", compileFileContent);
            FileGenerator.CreateFile(fgp);

            Process compileProcess = Process.Start(projectFolder + "\\" + "Compiler.bat");

            try
            {
                Process proc = new Process();
                proc.StartInfo.WorkingDirectory = projectFolder;
                proc.StartInfo.FileName = "Compile.bat";

                proc.StartInfo.CreateNoWindow = true;
                proc.Start();
                proc.WaitForExit();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception Occurred :{0},{1}",
                          ex.Message, ex.StackTrace.ToString());
            }
        }
    }
}
